from __future__ import annotations
from typing import TYPE_CHECKING, NamedTuple

import zipfile
from pathlib import Path
from bs4 import BeautifulSoup
import bs4

class TextPosition(NamedTuple):
    spine: int
    sequence: list[int]

class Book:
    def __init__(self, book_path: str | Path) -> None:
        self.book_path = Path(book_path)
        # resource_id: path
        self.resource_to_path: dict[str, str] = {}
        self.resource_to_spine_order: dict[str, int] = {}
        self.spine_order_to_resource: dict[int, str] = {}
        self.resource_to_bs: dict[str,BeautifulSoup] = {}
        self._open()

    def _open(self) -> None:
        with zipfile.ZipFile(self.book_path, 'r') as f:
            content = BeautifulSoup(f.read('OEBPS/content.opf'), 'xml')
            for item in content.find('manifest').find_all('item'):
                self.resource_to_path[item['id']] = 'OEBPS/' + item['href']
            
            for index, item in enumerate(content.find('spine').find_all('itemref')):
                item_id = item['idref']
                self.resource_to_spine_order[item_id] = index
                self.spine_order_to_resource[index] = item_id
            
            for resource_id in list(self.resource_to_spine_order):
                if resource_id != 'nav.xhtml':
                    resource_soup = BeautifulSoup(f.read(self.resource_to_path[resource_id]), 'xml')
                    for item in resource_soup.find('body').next_elements:
                        if isinstance(item, bs4.Tag):
                            item.attrs = {}
                    self.resource_to_bs[resource_id] = resource_soup

    def get_element(self, position: TextPosition) -> str:
        resource_id = self.spine_order_to_resource[position.spine]
        resource_soup = self.resource_to_bs[resource_id]
        tag = resource_soup
        for index in position.sequence:
            tag = tag.contents[index]
        return tag

    def extract_text(self, start: TextPosition, end: TextPosition) -> str:
        texts: list[str] = []
        start_soup = self.resource_to_bs[self.spine_order_to_resource[start.spine]]
        pass
    

if __name__ == '__main__':
    book_path = Path('./test_resource/景岳全书.epub')
    book = Book(book_path)
    tg = book.get_element(TextPosition(2, [1,3,13]))
    tg
